<!-- 
    需要根据内容自适应请写minWidth
    定义slots与width不会自适应
 -->
<template>
  <!-- 
      :auto-resize="true"//父元素变化重新计算表格
   -->
  <vxe-table
    :class='{ isNoBorder: !border }'
    :border='border'
    :data='tableData'
    :max-height='height'
    :show-header='showHeader'
    :loading='loading'
    cell-class-name='cellStyle'
    @checkbox-all='selectAllChangeEvent'
    @checkbox-change='onSelectChange'
    header-row-class-name='headerStyle'
    :span-method='mergeRowMethod'
    ref='vxeTable'
    :auto-resize='true'
  >
    <template v-for='config in headerColumn'>
      <vxe-column
        :key='config.field'
        :type='config.type'
        :field='config.field'
        :title='config.title'
        :fixed='config.fixed'
        :width='config.width'
        :filters='config.filters'
        :align='config.align'
        :formatter='config.formatter'
        :min-width='config.minWidth'
        :show-overflow='config.showOverflow'
      >
        <template #header='{ row }' v-if='config.headerSlots'>
          <slot :name='config.headerSlots' :row='row'></slot>
        </template>
        <template #content='{ row, rowIndex }' v-if="config.type == 'expand'">
          <slot :name='config.slots' :row='row' :rowIndex='rowIndex'></slot>
        </template>
        <template #default='{ row, column }' v-else-if='config.slots'>
          <slot :name='config.slots' :row='row' :column='column'></slot>
        </template>
      </vxe-column>
    </template>
  </vxe-table>
</template>

<script>
export default {
  name: "VxeTables",
  props: {
    tableData: {
      type: Array,
      default: () => []
    },
    tableColumn: {
      type: Array,
      default: () => []
    },
    border: {
      type: Boolean,
      default: true
    },
    height: {
      type: String,
      default: "auto"
    },
    showHeader: {
      type: Boolean,
      default: true
    },
    loading: {
      type: Boolean,
      default: false
    },
    mergeFields: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      headerColumn: []
    }
  },
  watch: {
    /**
     * 监控表格的数据data，自动设置表格宽度
     * @param valArr
     */
    tableData(valArr) {
      this.resetColumnWidth(valArr)
    }
  },
  methods: {
    onSelectChange({ row }) {
      const records = this.$refs.vxeTable.getCheckboxRecords()
      this.$emit("selectionChange", row, records)
    },
    selectAllChangeEvent({ records }) {
      this.$emit("selectAllChangeEvent", records)
    },
    // 通用行合并函数（将相同多列数据合并为一行）
    mergeRowMethod({ row, _rowIndex, column, visibleData }) {
      if (!this.mergeFields.length) return false
      const fields = this.mergeFields
      const cellValue = row[column.property]
      if (cellValue && fields.includes(column.property)) {
        const prevRow = visibleData[_rowIndex - 1]
        let nextRow = visibleData[_rowIndex + 1]
        if (prevRow && prevRow[column.property] === cellValue) {
          return { rowspan: 0, colspan: 0 }
        } else {
          let countRowspan = 1
          while (nextRow && nextRow[column.property] === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex]
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 }
          }
        }
      }
    },
    getCheckboxRecords() {
      return this.$refs.vxeTable.getCheckboxRecords()
    },
    /**
     * 遍历列的所有内容，获取最宽一列的宽度
     * @param arr
     */
    getMaxLength(arr) {
      return arr.reduce((acc, item) => {
        if (item) {
          let calcLen = this.getTextWidth(item)
          if (acc < calcLen) {
            acc = calcLen
          }
        }
        return acc
      }, 0)
    },
    /**
     * 使用span标签包裹内容，然后计算span的宽度 width： px
     * @param valArr
     */
    getTextWidth(str) {
      let width = 0
      let html = document.createElement("span")
      html.innerText = str
      html.className = "getTextWidth"
      document.querySelector("body").appendChild(html)
      width = document.querySelector(".getTextWidth").offsetWidth
      document.querySelector(".getTextWidth").remove()
      return width
    },
    resetColumnWidth(valArr) {
      const _this = this
      this.headerColumn = this.tableColumn.map(function(value) {
        // 根据最小宽去计算根据内容自适应
        if (value.minWidth) {
          const arr = valArr.map(x => x[value.field]) // 获取每一列的所有数据
          arr.push(value.title) // 把每列的表头也加进去算
          value.minWidth = _this.getMaxLength(arr) + 20 // 每列内容最大的宽度 + 表格的内间距(依据实际情况而定)
        }
        return value
      })
    }
  },
  created() {
    this.resetColumnWidth(this.tableData)
  }
}
</script>

<style lang='scss' scoped>
.vxe-table {
  width: 100%;

  ::v-deep .cellStyle {
    padding: 6px 0;
    height: 48px;
    white-space: nowrap;
  }

  ::v-deep .headerStyle {
    background: #f8f9fa;
  }

  &.isNoBorder ::v-deep .vxe-table--border-line {
    border: none;
  }
}

// 展开表头样式
::v-deep .expand_wrap {
  .headerStyle {
    background: #edf2ff;
  }

  .vxe-table .vxe-table--border-line {
    border-top: 1px solid #e8eaec;
    border-left: 1px solid #e8eaec;
    border-bottom: 1px solid #e8eaec;
  }
}
</style>
